package com.gitee.wsl.doc.prosemirror.state

import com.gitee.wsl.func.Function
import com.gitee.wsl.func.plus


typealias CommandDispatch = Function<Transaction,Unit>


//  Commands are functions that take a state and a an optional transaction dispatch function and...
//
//   - determine whether they apply to this state
//   - if not, return false
//   - if `dispatch` was passed, perform their effect, possibly by passing a transaction to `dispatch`
//   - return true
//typealias Command = (
//    state: PMEditorState,
//    dispatch: ((tr: Transaction) -> Unit)?
////  In some cases, the editor view is passed as a third argument.
////     view: EditorView?
//) -> Boolean
fun interface Command{
    fun exec(state: EditorState, dispatch: CommandDispatch?):Boolean
    operator fun invoke(state: EditorState, dispatch: CommandDispatch?):Boolean = exec(state,dispatch)

    companion object
}

operator fun Command.plus(other:CommandDispatch) = Command{ state, function ->
    this@plus.invoke(state,function + other)
}

fun EditorState.actionCommand(command: Command) :EditorState{
    var state = this
    command(state) { tr ->
        state = state.apply(tr)
    }
    return state
}

/// Combine a number of command functions into a single function (which
/// calls them one by one until one returns true).
fun chainCommands(vararg commands: Command): Command {
    return Command { state, dispatch->
        commands.forEach {
            if(it.exec(state,dispatch)) return@Command true
        }
        return@Command false
    }
}